import java.util.concurrent.atomic.AtomicInteger;

public class pc_static {
    private static final int NUM_END = 200000;
    private static final AtomicInteger COUNT = new AtomicInteger(); // 使用原子类实现质数计数

    private static int threadCount = 13;

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();

        // 每个线程的扫描哪些数据，存储在个二维数组里
        int[][] numbers = new int[threadCount][NUM_END / threadCount + 1];
        // 每个线程储存储在二维数组中的下一个数据的索引位置
        int[] indexs = new int[threadCount];
        // 开始遍历数据，把数据分配给每个线程
        for (int i = 1; i <= NUM_END; i++) {
            // 通过取余的方式进行分配，余数 = 数据/线程数，余数等于0分配给线程1，余数等于1分配给线程2,...
            int value = i % threadCount;
            // 数据分配所要分配的线程，这个线程在numbers中保存的扫描数据数组
            int[] numberTmp = numbers[value];
            // 这个数组最新数据应该存在哪个位置
            int index = indexs[value];
            // 数数分配
            numberTmp[index] = i;
            // 这个数组下一个数据存储的位置应该加1
            indexs[value]++;
        }

        Thread[] threads = new Thread[threadCount];
        for (int i = 0; i < threadCount; i++) {
            Thread thread = newThread(numbers[i], (i + 1));
            threads[i] = thread;
            thread.start();
        }

        for (int i = 0; i < threadCount; i++) {
            try {
                threads[i].join();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println("==========Execution Time:" + (System.currentTimeMillis() - startTime) + "ms" + ", count = " + COUNT.get());

    }

    private static Thread newThread(int[] numbers, int threadId) {
        AtomicInteger atomicInteger = new AtomicInteger();  // atomicInteger 传入 runable内，执行完后thread可以知道有多少prime
        Thread thread = new Thread(gerenateRunable(numbers, atomicInteger)) {
            @Override
            public void run() {
                long startTime = System.currentTimeMillis();

                super.run();

                long endTime = System.currentTimeMillis();
                long timeDiff = endTime - startTime;
                System.out.println("Execution Time:" + timeDiff + "ms, threadId = " + threadId + "\n" + "threadId = " + threadId + " # counter=" + atomicInteger.get());
//             System.out.println("threadId = " + threadId+ " # counter="+ atomicInteger.get());
            }
        };
        thread.setName(threadId + "");

        return thread;
    }

    private static Runnable gerenateRunable(int[] numbers, AtomicInteger atomicInteger) {

        return new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < numbers.length; i++) {
                    int value = numbers[i];
                    if (value <= 0) {
                        break;
                    }

                    if (isPrime(value)) {
                        atomicInteger.incrementAndGet();
                        COUNT.incrementAndGet();

                    }
                }
            }
        };

    }


    private static boolean isPrime(int x) {  //判断质数
        int i;
        if (x < 1) {
            return false;
        }
        for (i = 2; i < x; i++) {
            if ((x % i == 0) && (i != x)) {
                return false;
            }
        }
        return true;
    }
}